# -*- coding: utf-8 -*-
# @Time     : 2021/12/4 19:43
# @Author   : wljess
# @File     : __solts__用法.py
# @Describe : 
# @Software : PyCharm
"""
类中定义一个变量__slots__，它的作用是阻止在实例化类时为实例分配dict。
由于每次实例化一个类都要分配一个新的dict，因此存在空间的浪费，因此有了__slots__。
当定义了slots后，slots中定义的变量变成了类的描述符。
类的实例只能拥有slots中定义的变量，不能再增加新的变量。注意：定义了slots后，就不再有dict。

Python的新式类和经典类的实例都有一个 dict来存储实例的属性。这在一般情况下还不错，而且非常灵活，
乃至在程序中可以 随意设置新的属性。但是，对一些在”编译”前就知道有几个固定属性的小class来说，
这个dict就有点浪费内存了。当需要创建大量实例的时候，这个问题变得尤为突出。一种解决方法是在
新式类中定义一个__slots__属性。
__slots__声明中包含若干实例变量，并为每个实例预留恰好足够的空间来保存每个变量；这样Python就不会再使用dict，
从而节省空间


"""


class MyClass:
    __slots__ = ("name", "age", "sex")
    # 若类变量与__slots__中变量名相同，就会抛如下错：ValueError: 'age' in __slots__ conflicts with class variable
    # age = 20
    desc = "hello world"

    def __init__(self, name):
        self.name = name


class Son(MyClass):
    pass


son = Son('刘德华')
# 显然，__slots__ 属性只对当前所在的类起限制作用。
# 因此，如果子类也要限制外界为其实例对象动态地添加属性和方法，必须在子类中设置 __slots__ 属性。
son.height = 175
print(son.height)
obj = MyClass('李白')

print(MyClass.desc)
MyClass.desc = "hello python"
print(MyClass.desc)

print(obj.name)
print(obj.__slots__)
obj.age = 18
obj.sex = "male"
print(obj.age)
print(obj.sex)

print(dir(MyClass))
# AttributeError: 'MyClass' object has no attribute '__dict__'
# print(obj.__dict__)
# 创建类的时候定义了：__slots__ = ("name", "age", "sex")，表明对象除了"name", "age", "sex"属性以外，
# 不能添加其他属性
# obj.height = 175
# print(obj.height)

